#!/usr/bin/perl 
#
# (C) Copyright 2010- Hewlett-Packard Development Company, L.P.
#
# $Id: sqconfig_gen 17950 2012-05-08 07:47:06Z cheng-xin.cai@hp.com $
#

use strict;
use 5.008000;
use warnings;
use POSIX;
use Getopt::Long; 
use File::Basename;
use Data::Dumper;

use lib '/opt/hp/nv/lib/perl';
use config ':all';
use instance ':all';

# possible error returns
use constant {
    OK => 0,
    WARN => 1,
    CRITICAL => 2,
    UNKNOWN => 3,
};

# Global variables

# common global variables
my $proceed=1;
my $done=0;

my $myscriptname = "rmsquser";
my $status_file = "$nvpath/instance/status/" . $myscriptname;
my $revision = '$Revision: 17037 $';
$revision =~ s/\$//g;

# script specific globals

use constant SQCONFIGTEMPLATE => "$nvpath/config/sqconfig_template";
use constant NODESPERENCLOSURE => 11; # max number of nodes per enclosure
use constant {
    SHAREDTLOGLOGICALNODE => 1, # logical node id for TLOG
    SHAREDTLOGNODE => 3,        # physical node number for TLOG
    SHAREDSYSTEMLOGICALNODE => 2, # logical node id for SYSTEM
    SHAREDSYSTEMNODE => 4,        # physical node number for SYSTEM
};
use constant {
    CONNECTION => "connection",
    AGGREGATION => "connection,aggregation,storage",
    SPARE => "spare"
};

# define some standard values
my $SQLNODES = 8;
my $EDGENODES = 1;
my $SPARENODES = 1;
my $TSEPERASE = 4;

my $gv_lowest_core = 1024;  # give it a big number as the initial value
my $gv_sqconfigfile;

# command line options
my %gv_opts = (maxtse => 8
              );

# DO NOT DELETE/DO NOT MODIFY
#
# This sub calls module routine to log informational message to log file
# after first prepending program name; timestamp will be added in
# Perl module
#
sub log_msg
{
    my $message = shift;
    my $infomessage;

    $infomessage = basename($0) . ": INFO: ". $message . "\n";
    instance_log_event($infomessage);

}

# DO NOT DELETE/DO NOT MODIFY
#
# This sub calls module routine to log warning message to log file
# after first prepending program name and Warning label; a timestamp
# will be added in Perl module
#
sub log_warn
{
    my $message = shift;
    my $warnmessage;

    $warnmessage = basename($0) . ": WARNING: ". $message . "\n";
    instance_log_event($warnmessage);

}

# DO NOT DELETE/DO NOT MODIFY
#
# This sub calls module routine to log error message to log file
# after first prepending program name; timestamp will be added in
# Perl module; the program will then exit
#
sub logerr_n_die
{
    my $message = shift;
    my $errormessage;

    $errormessage = basename($0) . ": ERROR: ". $message . "\n";
    print STDERR $errormessage;
    
    instance_log_event($errormessage);
    exit(CRITICAL);

}

# CHANGE FOR YOUR NEEDS
#
# This sub checks for any requirements that must be met before
# the configuration is performed.
#
sub pre_req_check
{
    # if hyperthreading is not disabled then we cannot proceed.
    my $ht_enabled = get_hyperthreading();
    logerr_n_die("Hyperthreading has not been disabled.  Cannot proceed.") if ($ht_enabled);

    return(OK);
}

# CHANGE FOR YOUR NEEDS
#
# This sub verifies that the work done is complete and in such a state
# that it is ready for the next step to be done
#
sub post_check
{
    if ( $gv_sqconfigfile && !-e $gv_sqconfigfile) {
        logerr_n_die("sqconfig file not created. Cannot proceed.");
    }

    return(OK);
}

# CHANGE FOR YOUR NEEDS
#
# This sub checks the script status to determine whether
# the script has already been run successfully.
# The status file could just hold "completed", for example,
# or it could hold a count of how many things were processed last time,
# e.g. number of nodes, or number of disks, etc.  So that a comparison
# can be made to see if processing must be done again.
#
sub get_status(;$)
{
    my $prefix = shift;
    $prefix = '' unless (defined $prefix);
        
    # Keep the open and close of the file along with the line processing

    # if we haven't yet written this file then we surely must proceed
    return($proceed) if (!-e $status_file);

    open(IFH,$status_file) || logerr_n_die("Can't open file $status_file: $!");
    while (<IFH>) # loop through the whole file
    {
        next if (/^\s*$/);
        next if (/^\#/);

        # ADD HERE THE PROCESSING THAT MAKES SENSE FOR YOUR CODE!
        # IN THIS EXAMPLE WE CHECK FOR 'completed'
        if (/^$prefix:completed/) {
            close(IFH);
            return($done);
        }
    }
    close(IFH);
    return($proceed);
}

# CHANGE FOR YOUR NEEDS
#
# This sub sets the script status to be examined
# the next time the script is run.
# The status file could just hold "completed", for example,
# or it could hold a count of how many things were processed last time,
# e.g. number of nodes, or number of disks, etc.  So that a comparison
# can be made to see if processing must be done again.
#
sub set_status($;$)
{
    my ($statusmsg, $prefix) = @_;        
    # Keep the open and close of the file
    open(OFH,">>$status_file") || logerr_n_die("Can't open file $status_file: $!");

    # ADD HERE THE PROCESSING THAT MAKES SENSE FOR YOUR CODE!
    print OFH "$prefix:$statusmsg\n";

    close(OFH);

}

# CHANGE FOR YOUR NEEDS
#
# This sub verifies that the work done is complete and in such a state
# that it is ready for the next step to be done
#
sub perform_config
{
    # Keep the following checks to determine whether the
    # script is being forced to be re-run, and to check
    # whether this script completed successfully
    #
    
    my $force_flag = get_force_flag();
    my $status_value = get_status($gv_opts{squser});

    return(OK) if (!$force_flag && ($status_value == $done));

    my %cores = create_corelist();
    my %roles = assign_roles();

    create_sqconfig(\%cores, \%roles);

    # Keep the following code to set the status to completed
    # and return success.
    set_status("completed", $gv_opts{squser});
    return(OK);
}

#
# This sub will check for the presence of SSDs on the slave nodes.  If found, then a flag will be set.
# Otherwise, the flag remains set to 0.  This information is used when creating the sqconfig file later on.
#
sub check_for_SSDs
{
    log_msg("Checking for the presence of SSDs on the slave nodes:");

    # Run command on one of the slave nodes to determine whether SSDs are found.
    # Since SSDs are either everywhere or nowhere we can use 1 node to tell us what to do.
    # We pick $FIRSTSLAVE to check for SSDs since that should be present on any size system
    #
    # [root@atcsq01-hn1 /]# /usr/bin/ssh  n011 service ssdconfig status
    # SSD RAID volume has been configured (/etc/mdadm.conf exists)
    # 
    # 
    # SSD volume is mounted: /ssd (2.2T/2.3T available)
    # mdadm daemon monitoring the SSD RAID volume (PID: 9258)
    # [root@atcsq01-hn1 /]# echo $?
    # 0
    # [root@atcsq01-hn1 /]# /usr/bin/ssh  n003 service ssdconfig status
    #  No SSD devices detected
    # [root@atcsq01-hn1 /]# echo $?
    # 1
    #
    my @nodes = get_instance_nodelist($gv_opts{squser});
    my $first = $nodes[0];
    my $cmd = "/usr/bin/ssh $first /sbin/service ssdconfig status 2>&1";

    `$cmd`;

    # Check for bad exit status
    if (WIFEXITED($?) && (WEXITSTATUS($?) == 0)) {
        # Zero value returned, which tells us that there are SSDs configured
        # so we return 1
        return 1;
    }
    else {
        return 0; # no SSDs
    }
}

#
# This sub creates core hash from Bright Cluster cmsh
#
sub create_corelist
{
    # now let's create core hash with the node name as the hash key!!
    # we just create the core hash for nodes in all nodes
    my @nodes = get_instance_nodelist($gv_opts{squser});
    my %cores;
    foreach my $node (@nodes) {
        my @fields = split /,/, get_node_processor_info($node);

        $cores{$node} = $fields[0] * $fields[1];
        $gv_lowest_core = $cores{$node}  if ($cores{$node} < $gv_lowest_core);
    }

    $gv_lowest_core = $gv_opts{maxtse} if ($gv_lowest_core > $gv_opts{maxtse});     

    return %cores;
}

#
# This sub assigns roles to nodes
# The values for EDGENODES, SQLNODES and SPARENODES are defined at the top
# of the file, so these can be modified as needed.
#
# On typical enclosure 1st $EDGENODES are connection roles, 
# next $SQLNODES are aggregation roles 
# and the next $SPARENODES are spares.
#
sub assign_roles
{
    my %roles;

    # get all the enclosures
    my @racks = get_instance_racklist($gv_opts{squser});

    for my $rack (@racks) {
        my @nodes = get_nodes_in_rack($rack);

        my $node;
        # 1st $EDGENODES are connection only roles
        for $node (@nodes[0 .. $EDGENODES-1]) {
            $roles{$node} = CONNECTION;
        }

        # next $SQLNODES are aggregation roles
        for $node (@nodes[$EDGENODES .. $SQLNODES+$EDGENODES-1]) {
            $roles{$node} = AGGREGATION;
        }

        # currently we don't support spare nodes so comment out these codes
        # and the next $SPARENODES are spares.
        #for $node (@nodes[$SQLNODES+$EDGENODES .. $SQLNODES+$EDGENODES+$SPARENODES-1]) {
        #    $roles{$node} = SPARE;
        #}

    }
    return %roles;
}

#
# This sub creates the sqconfig file given the cores found and roles assigned to nodes
#
sub create_sqconfig($$)
{

my $cores = shift;
my $roles = shift;

    my @physical_nodes = ();   
    my %nodeid;      

    my $instancetype = get_inst_config_type();
    my $clustername = get_cluster_name();
    
    if ($instancetype eq "sliced") {
        $gv_sqconfigfile = "$nvpath/instance/sqconfig_${clustername}_$gv_opts{squser}";
    }
    elsif ($instancetype eq "shared") {
        $gv_sqconfigfile = "$nvpath/instance/sqconfig_${clustername}_squserN";
    } 
    my $sqconfigBAK = $gv_sqconfigfile . '.BAK';
    
    # if a backup copy exists then remove it so we can
    # save a backup of the current version
    unlink($sqconfigBAK) if ( -e $sqconfigBAK);

    # now save a backup copy of the file before we create new
    rename $gv_sqconfigfile, $sqconfigBAK if ( -e $gv_sqconfigfile);

    # Set up the files to manipulate
    open(FILE, SQCONFIGTEMPLATE)  || logerr_n_die("Can't open sqconfig_template: $!");
    open(OUTFILE,">$gv_sqconfigfile") || logerr_n_die("Can't open $gv_sqconfigfile: $!");

    my @nodes = get_instance_nodelist($gv_opts{squser});
    
    my $last_lun;  # lun for ase and tse (shared system)
    my $tmase_lun; # lun for tlog and system (shared system)
    
    # lun for tlog and system are fixed, so, generate it here    
    $tmase_lun = $gv_lowest_core + $gv_lowest_core/$TSEPERASE + 1; 
    
    my $line;
    while ($line=<FILE>) { # loop through the whole file
        chomp($line);
        
        if ($line =~ /template sqconfig file/) {
            print(OUTFILE "# This sqconfig file created by sqconfig_gen script\n");
        } 
        elsif ($line =~ /begin enclosure/) {
            print(OUTFILE "$line\n");

            my @racks = get_instance_racklist($gv_opts{squser});
            for my $rack (sort @racks) {
                my $nodes = lc(get_nodes_in_rack($rack));
                print OUTFILE "enc-rack$rack=$nodes\n";
            }
        } 
        elsif ($line =~ /begin node/) {
            print(OUTFILE "$line\n");

            my $nid = 0;

            my ($connection_output, $aggregation_output);

            my $top_core = $gv_lowest_core - 1;

            # check for aggregation first
            my @racks = get_instance_racklist($gv_opts{squser});
            my $rack;
            for $rack (sort @racks) {
                my @nodes = get_nodes_in_rack($rack);
                for my $node (sort @nodes) {
                    next if (!defined($roles->{$node}) || $roles->{$node} ne AGGREGATION);

                    my @fields = split /,/, get_node_processor_info($node);
                    my $procs = $fields[0];

                    $aggregation_output .= sprintf("node-id=$nid;node-name=%s;cores=0-$top_core;processors=$procs;roles=$roles->{$node}\n",
                        lc($node));
                   
                    push @physical_nodes, $node;
                    $nodeid{$node} = $nid;

                    $nid++;
                }
            }

            # currently we don't support spare nodes so comment out these codes
#            # second the spare node
#            for $rack (sort @racks) {
#                my @nodes = get_nodes_in_rack($rack);
#                for my $node (sort @nodes) {
#                    next if (!defined($roles->{$node}) || $roles->{$node} ne SPARE);
#                    
#                }
#            }

            # at last the connection node 
            for $rack (sort @racks) {
                my @nodes = get_nodes_in_rack($rack);
                for my $node (sort @nodes) {
                    next if (!defined($roles->{$node}) || $roles->{$node} ne CONNECTION);

                    my @fields = split /,/, get_node_processor_info($node);
                    my $procs = $fields[0];

                    $connection_output .= sprintf("node-id=$nid;node-name=%s;cores=0-$top_core;processors=$procs;roles=$roles->{$node}\n",
                        lc($node));
                   
                    push @physical_nodes, $node;
                    $nodeid{$node} = $nid;

                    $nid++;

                }
            }

            print OUTFILE $connection_output;
            print OUTFILE $aggregation_output;

        } 
        elsif ($line =~ /begin ase/) { ## AUXXXX
            print(OUTFILE "$line\n");
            print(OUTFILE "#VolumeName\tnode-id\t\tmirror location #1\t\t\tmirror location #2\n");
            print(OUTFILE "#==========\t=======\t\t==================\t\t\t==================\n");

            # Since we will have 1 ASE for each $TSEPERASE cores(TSEs)
            # then we need to find out how many cores in each logical node
            # and decide how many lines we need per logical node
            # e.g. if 8 cores, then 2 ASEs per logical but if 4 then only 1 per..
            # But if we want to max out the number of TSEs then we need to adjust
            # the number of ASEs accordingly

            my $lines_per_logical = $gv_lowest_core/$TSEPERASE;
            
            my $aud_index = 1;
            if ($instancetype eq "sliced") {
                foreach my $node (@physical_nodes) {
                    next if ($roles->{$node} ne AGGREGATION);

                    my $nid = $nodeid{$node};
                    for (my $count = 1; $count <= $lines_per_logical; $count++) {
                        printf(OUTFILE "\$AU%04d\t\t%s\t\t/database\/$gv_opts{squser}\t\t\t/databasem\/$gv_opts{squser}\n", $aud_index, $nid);
                       
                        $aud_index++;
                    }
                }
            } 
            elsif ($instancetype eq "shared") {
                foreach my $node (@physical_nodes) {
                    next if ($roles->{$node} ne AGGREGATION);

                    my $nid = $nodeid{$node};

                    my $nodenum = $node;
                    $nodenum =~ s/^n0*//i;
                    
                    for (my $count = 1; $count <= $lines_per_logical; $count++) {
                        printf (OUTFILE "\$AU%04d\t\t%s\t\t/database/n%du%d/squserN\t\t\t/databasem/n%du%d/squserN\n", $aud_index, $nid, $nodenum, $count, $nodenum, $count);
                        
                        $aud_index++;
                    }
                }
                #remember the lunnum for tse
                $last_lun = $lines_per_logical;
            }

        } 
        elsif ($line =~ /begin tmase/) { ## TLOG
            print(OUTFILE "$line\n");
            print(OUTFILE "#VolumeName\tnode-id\t\tmirror location #1\t\t\tmirror location #2\n");
            print(OUTFILE "#==========\t=======\t\t==================\t\t\t==================\n");
            
            if ($instancetype eq "sliced"){
                print OUTFILE "\$TLOG\t\t0\t\t/database\/$gv_opts{squser}\t\t\t/databasem\/$gv_opts{squser}\n";
            } 
            elsif ($instancetype eq "shared") {
                my $nodenum = SHAREDTLOGNODE;
                my $logicalnodenum = SHAREDTLOGLOGICALNODE;
                
                printf OUTFILE "\$TLOG\t\t%d\t\t/database/n%du%d/squserN\t\t\t/databasem/n%du%d/squserN\n",
                    $logicalnodenum, $nodenum, $tmase_lun, $nodenum, $tmase_lun;
            }

        } 
        elsif ($line =~ /begin tse/) { ## SYSTEM and DBXXXX
            print(OUTFILE "$line\n");
            print(OUTFILE "#VolumeName\tnode-id\t\tmirror location #1\t\t\tmirror location #2\n");
            print(OUTFILE "#==========\t=======\t\t==================\t\t\t==================\n");
    
            # We will have 1 TSE for each core
            # so loop through the core count and generate entries per core
            # unless we have defined a maximum number of TSEs in which
            # case we will define that man TSEs
            my $lines_per_logical = $gv_lowest_core;
 
            my $tse_index = 1;
            if ($instancetype eq "sliced") {
                # generate the one $SYSTEM entry for this section
                print(OUTFILE "\$SYSTEM\t\t0\t\t/database\/$gv_opts{squser}\t\t\t/databasem\/$gv_opts{squser}\n");
                foreach my $node (@physical_nodes) {
                    next if ($roles->{$node} ne AGGREGATION);

                    my $nid = $nodeid{$node};            
                    for (my $count = 1; $count <= $lines_per_logical; $count++) {
                        printf(OUTFILE "\$DB%04d\t\t%s\t\t/database\/$gv_opts{squser}\t\t\t/databasem\/$gv_opts{squser}\n", $tse_index, $nid);
                        
                        $tse_index++;
                    }
                }
            } 
            elsif ($instancetype eq "shared") {
        # in a shared environment the SYSTEM volume is hardcoded 
                my $nodenum = SHAREDSYSTEMNODE;
                my $logicalnodenum = SHAREDSYSTEMLOGICALNODE;
                
                printf (OUTFILE "\$SYSTEM\t\t%s\t\t/database/n%du%d/squserN\t\t\t/databasem/n%du%d/squserN\n", $logicalnodenum, $nodenum, $tmase_lun, $nodenum, $tmase_lun);
                
                foreach my $node (@physical_nodes) {
                    next if ($roles->{$node} ne AGGREGATION);

                    my $nid = $nodeid{$node};            

                    my $nodenum = $node;
                    $nodenum =~ s/^n0*//i;
 
                    for my $count ($last_lun+1 .. $last_lun + $lines_per_logical) {
                        printf(OUTFILE "\$DB%04d\t\t%s\t\t/database/n%du%d/squserN\t\t\t/databasem/n%du%d/squserN\n", $tse_index, $nid, $nodenum, $count, $nodenum, $count);
                        
                        $tse_index++;

                    }
                }
            }

        } 
        elsif ($line =~ /begin overflow/) {
            print(OUTFILE "$line\n");

            # if  we have determined that this cluster has SSDs then
            # add in the appropriate SSD line
            if (check_for_SSDs()) {
                print(OUTFILE "ssd /ssd/$gv_opts{squser}\n");
            }
        } 
        elsif ($line =~ /begin bdr/) {
            # Get BDR clustername.
            my $bdrname = get_instance_bdrname($gv_opts{squser});

            # lets obtain 2 nodes with external connectivity and have them ready for
            # ready for however BDR was configured

            # Use the keys of our arrays, which is the node names
            my ($firstbdrnode, $secondbdrnode) = @nodes[0, 1];    

            for my $nodes (@nodes[2 .. $#nodes]) {
                if (defined $roles->{$nodes} && $roles->{$nodes} eq "connection") {
                    $secondbdrnode = $nodes;
                }
            }
            my $float;
            if ( get_instance_floatIP_flag($gv_opts{squser}) eq 'yes' ){
                $float = 1;
            }
            $float = 0 if ($instancetype eq "shared");

            if ($float) {

            # Get the external and internal floating IP from the instance.conf file
            my $floatint = get_instance_int_floatIP($gv_opts{squser});
            my $floatext = get_instance_ext_floatIP($gv_opts{squser});

            # call subroutine to figure out the internal
            # and external devices on slave nodes
            # this is needed in the floating IP section
            my ($intdev, $extdev) = get_devices();  #eth0, eth1

                print(OUTFILE "begin floating_ip\n");
                print(OUTFILE "process=\$MXOAS;interface=$extdev;external-ip=$floatext\n");
                print(OUTFILE "process=\$MXOAS;interface=$intdev;internal-ip=$floatint\n");
                
                my $firstbdrnodeid = $nodeid{$firstbdrnode};
         my $secondbdrnodeid = $nodeid{$secondbdrnode};
            
                print(OUTFILE "floating_ip_node_id $firstbdrnodeid\n");
                print(OUTFILE "floating_ip_failover_node_id $secondbdrnodeid\n");
                print(OUTFILE "end floating_ip\n");

                # now setup BDR (bulk data replicator)
                print(OUTFILE "\n$line\n");
                print(OUTFILE "bdr_cluster_name $bdrname\n");
                print(OUTFILE "bdr_ip_address floating\n");
                print(OUTFILE "bdr_node_id floating\n");
                print(OUTFILE "bdr_port_number 17500\n");

            } 
            else { # float eq "no"

                # setup BDR (bulk data replicator)
                print(OUTFILE "$line\n");

                print(OUTFILE "bdr_cluster_name $bdrname\n");
                
                # use the nodename obtained above, and then find out
                # what the external IP address of the edge node is.
                my $cmd = "cmsh -c \"device ; use $firstbdrnode; interfaces; list \" |  grep externalnet";

                my $externalline = `$cmd`;
                # Check for bad exit status
                if (WIFEXITED($?) && (WEXITSTATUS($?) != 0)) {
                    logerr_n_die("Unable to obtain a list of interfaces for node $firstbdrnode: " . $?);
                }
            
                # split on whitespace
                my $ip = (split(/\s+/, $externalline))[2];
                print(OUTFILE "bdr_ip_address $ip\n");

                # node id of first edge node
                print(OUTFILE "bdr_node_id $nodeid{$firstbdrnode}\n");
    
                # Set port number to 17500 (starting port)
                print(OUTFILE "bdr_port_number 17500\n");

            } # if then else of if using floating IP addresses or not.. 
        } 
        else {

            # just repeat line in file
            print(OUTFILE "$line\n");
        }

    }  # end while there are lines in sqconfig template file

    close(FILE); 
    close(OUTFILE);
    
    set_instance_sqconfig($gv_opts{squser}, $gv_sqconfigfile);
}

#
# This sub will obtain the device used for internal network on the slave
# and the device used for the external network on the slave
# We need to look at slave because headnodes could be different 
# AND this assumes that ALL SLAVES ARE CONFIGURED THE SAME WAY!
#
sub get_devices
{
    my @nodes = get_instance_nodelist($gv_opts{squser});
    my $slavenode = $nodes[0];

    # get the device that is used for the external network
    # on the slaves; use $slavenode as an example
    # NOTE: This assumes that all slaves are configured the
    # same way.  If they are not then we will need something
    # that will run on each individual node.
    my $cmd = "cmsh -c \"device; use $slavenode; interfaces; list\" | grep externalnet";

    my $externalline = `$cmd`;
    # Check for bad exit status
    if (WIFEXITED($?) && (WEXITSTATUS($?) != 0)) {
        logerr_n_die("Unable to determine external device on slave: " . $?);
    }

    my @fields = split(/\s+/, $externalline);
    my $extdev = $fields[1];

    # get the device that is used for the internal network
    # on the slaves; use $slavenode as an example
    # NOTE: This assumes that all slaves are configured the
    # same way.  If they are not then we will need something
    # that will run on each individual node.
    $cmd = "cmsh -c \"device; use $slavenode; interfaces; list\" | grep internalnet";

    chomp (my $BOOTIFline = `$cmd`);
    # Check for bad exit status
    if (WIFEXITED($?) && (WEXITSTATUS($?) != 0)) {
        logerr_n_die("Unable to determine internal device on slave: " . $?);
    }

    # the command above does not give me an ethx device name, unfortunately.  The output will
    # look like the following:  NetworkPhysicalInterface BOOTIF 172.31.0.1 internalnet
    # so now I need to get the address so that I can find the device in ifconfig output
    @fields = split(/\s+/, $BOOTIFline);
    my $IPaddr = $fields[2];

    # now that I have the address, I can find the device name associated with that
    # address in the ifconfig output
    # NOTE: The use of this command assumes that the slave node is up and running
    # in order for me to pdsh to it and perform an ifconfig command.  However, I can
    # find no other way to get this info via Bright!!!
    $cmd = "/usr/bin/ssh -o ConnectTimeout=5 $slavenode \"/sbin/ifconfig | grep -R5 $IPaddr | grep eth\" ";

    chomp (my $internalline = `$cmd`);
    # Check for bad exit status
    if (WIFEXITED($?) && (WEXITSTATUS($?) != 0)) {
        logerr_n_die("Unable to obtain internal device name from ifconfig on slave:" . $?);
    }

    @fields = split(/\s+/, $internalline);
    my $intdev = $fields[0];
        
    return ($intdev, $extdev);
}

#
# usage
#
sub usage
{
print <<"EOF";

This script will create an sqconfig file.

$myscriptname --squser=<squser name> [--maxtse=]
[--sql=] [--edge=] [--spare=] [--tseperase=]

--squser - identifies the name of the squser to be configured in the file; if not
    provided the default of "squser1" will be configured
--maxtse - identifies the maximum number of TSEs that should be configured on a node;
    if this value is not provided then one TSE is generated per core. If 
    specified, this value is also used in the ASE calculations, which is one 
    per four TSEs.
--sql, --edge, --spare and --tseperase are currently not supported.

EOF

exit(UNKNOWN);
}

### Main ###

# Process input arguments
&GetOptions(\%gv_opts,
            "squser=s",
            "maxtse=i",
            "sql=i",
            "edge=i",
            "spare=i",
            "tseperase=i") or usage();

log_msg("Starting script: revision number $revision");

if (! defined($gv_opts{squser})) {
    logerr_n_die("squser not defined");
}

my $tempsqlnodes = defined $gv_opts{sql} ? $gv_opts{sql} : $SQLNODES;
my $tempedgenodes = defined $gv_opts{edge} ? $gv_opts{edge} : $EDGENODES;
my $tempsparenodes = defined $gv_opts{spare} ? $gv_opts{spare} : $SPARENODES;

if (defined $gv_opts{sql} || defined $gv_opts{edge} || defined $gv_opts{spare}) {
    my $numservers = $tempsqlnodes + $tempedgenodes + $tempsparenodes;

    if ($numservers > NODESPERENCLOSURE ) {
        logerr_n_die ("Invalid input provided.  Total number of nodes cannot exceed " . NODESPERENCLOSURE);
    }
    else {
        $SQLNODES = $gv_opts{sql} if (defined $gv_opts{sql});
        $EDGENODES = $gv_opts{edge} if (defined $gv_opts{edge});
        $SPARENODES = $gv_opts{spare} if (defined $gv_opts{spare});
    }
}

$TSEPERASE = $gv_opts{tseperase} if (defined $gv_opts{tseperase});

pre_req_check;

perform_config;

post_check;

# Return success
exit(OK);
